﻿import re
import time
import itertools
import requests  # 添加requests库导入
from tqdm import tqdm

# 从网络URL读取diquma.json数据
try:
    response = requests.get('https://gitee.com/guigu77/tool/raw/master/idcard/diquma.json')
    response.raise_for_status()  # 检查请求是否成功
    diquma = response.json()
    print(f"成功加载地区码数据，共 {len(diquma)} 条记录")
except requests.exceptions.RequestException as e:
    print(f"加载地区码数据失败: {e}")
    # 如果网络请求失败，使用空字典作为备选
    diquma = {}

def address_lookup(card_address):
    x_count = card_address.lower().count('x')
    normalized_address = card_address.lower().replace('x', r'\d')
    pattern = re.compile(f'^{normalized_address}$')
    
    matched_areas = {}
    for code, name in diquma.items():
        if pattern.match(code):
            matched_areas[code] = name
    
    print(f"地址码需补齐 {x_count} 位，共有 {len(matched_areas)} 个匹配地区")
    for code, name in matched_areas.items():
        #print(f"{code}: {name}")
        pass
    return matched_areas.keys()

def check_id_length(n):
    return len(n) == 18

def check_id_data(n):
    if len(n) < 14:
        return False
    try:
        year = int(n[6:10])
        month = int(n[10:12])
        day = int(n[12:14])
    except ValueError:
        return False
    
    if year < 1950 or year > time.localtime().tm_year:
        return False
    if month < 1 or month > 12:
        return False
    if day < 1 or day > 31:
        return False
    
    if month in {4, 6, 9, 11} and day > 30:
        return False
    
    if month == 2:
        if (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0):
            if day > 29:
                return False
        else:
            if day > 28:
                return False
    return True

def check_id(n):
    if len(n) != 18:
        return False
    var = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
    var_id = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2']
    
    try:
        sum_val = 0
        for i in range(17):
            sum_val += int(n[i]) * var[i]
    except ValueError:
        return False
    
    sum_val %= 11
    return var_id[sum_val] == n[17]

def main():
    card = input('请输入身份证号码（用x代表未知数字）：').strip().upper()
    
    if len(card) != 18:
        print("警告：身份证号码长度不正确，应为18位！")
        if len(card) < 18:
            card = card.ljust(18, 'x')[:18]
        else:
            card = card[:18]
    
    card_address = card[:6]
    if 'X' in card_address:
        address_list = address_lookup(card_address)
    else:
        address_list = [card_address]
        print(f"地区: {diquma.get(card_address, '未知地区')}")
    
    card_sex = card[16]
    if card_sex != 'X':
        gender = "女" if int(card_sex) % 2 == 0 else "男"
        print(f"性别: {gender}")
    
    digits = []
    for i in range(18):
        if card[i] != 'X':
            digits.append([card[i]])
        else:
            if i == 16:
                gender_input = input("请输入性别（男/女/未知，直接回车跳过）：").strip()
                if gender_input == '男':
                    digits.append(['1', '3', '5', '7', '9'])
                elif gender_input == '女':
                    digits.append(['0', '2', '4', '6', '8'])
                else:
                    digits.append(['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'])
            elif i == 17: 
                digits.append(['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'X'])
            else:
                digits.append(['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'])

    total_possibilities = 1
    for d in digits:
        total_possibilities *= len(d)
    
    valid_ids = set()
    start_time = time.time()
    
    with tqdm(total=total_possibilities, desc="生成进度") as pbar:
        for candidate in itertools.product(*digits):
            id_str = ''.join(candidate)
            if id_str[:6] in address_list and check_id_data(id_str) and check_id(id_str):
                valid_ids.add(id_str)
            pbar.update(1)
    
    end_time = time.time()

    if valid_ids:
        with open('sfz.txt', 'w', encoding='utf-8') as f:
            for id_num in sorted(valid_ids):
                f.write(id_num + '\n')
        
        print(f"已保存到 sfz.txt 文件,总耗时: {end_time - start_time:.2f} 秒")
        print(f"有效身份证号码：{len(valid_ids)}")

    else:
        print("未能生成任何有效的身份证号码")

if __name__ == "__main__":
    main()